<template>
  <div class="chart-wrapper">
    <canvas ref="chartCanvas"></canvas>
  </div>
</template>

<script setup>
import { ref, onMounted, watch, onBeforeUnmount } from 'vue';

// 定义 props
const props = defineProps({
  data: {
    type: Array,
    required: true,
  },
  options: {
    type: Object,
    default: () => ({}),
  },
});

// 默认配置
const defaultOptions = {
  pointColor: '#ffffff', // 数据点颜色（白色）
  backgroundColor: ['#1e3c72', '#2a5298'], // 背景渐变色
  axisColor: ['#4facfe', '#00f2fe'], // 轴线渐变色
  gridColor: 'rgba(255, 255, 255, 0.1)', // 网格线颜色
  labelColor: '#fff', // 数据标签颜色
  topPadding: 30, // 顶部留白，确保标签显示
  bottomPadding: 20, // 底部留白，确保刻度线 0 不紧贴底部
  sidePadding: 40, // 左右两侧的留白距离
  pointRadius: 2, // 数据点半径
};

// 合并配置
const chartOptions = {
  ...defaultOptions,
  ...props.options,
};

// 引用 canvas 元素
const chartCanvas = ref(null);
let ctx = null; // canvas 上下文

// 初始化 canvas
const initCanvas = () => {
  if (chartCanvas.value) {
    const parent = chartCanvas.value.parentElement;
    chartCanvas.value.width = parent.clientWidth; // 宽度充满父容器
    chartCanvas.value.height = parent.clientHeight; // 高度充满父容器
    ctx = chartCanvas.value.getContext('2d');
    renderChart();
  }
};

// 绘制渐变背景
const drawBackground = () => {
  const { width, height, backgroundColor } = chartOptions;
  const gradient = ctx.createLinearGradient(0, 0, 0, height);
  gradient.addColorStop(0, backgroundColor[0]);
  gradient.addColorStop(1, backgroundColor[1]);
  ctx.fillStyle = gradient;
  ctx.fillRect(0, 0, width, height);
};

// 绘制网格线
const drawGridLines = () => {
  const { width, height, gridColor, topPadding, bottomPadding, sidePadding } = chartOptions;
  const maxX = Math.max(...props.data.map(point => point.x));
  const maxY = Math.max(...props.data.map(point => point.y));
  const stepX = (width - 2 * sidePadding) / 10; // 水平网格线间距
  const stepY = (height - topPadding - bottomPadding) / 10; // 垂直网格线间距

  ctx.strokeStyle = gridColor;
  ctx.lineWidth = 0.5;

  // 水平网格线
  for (let i = 0; i <= 10; i++) {
    const y = height - bottomPadding - i * stepY;
    ctx.beginPath();
    ctx.moveTo(sidePadding, y);
    ctx.lineTo(width - sidePadding, y);
    ctx.stroke();
  }

  // 垂直网格线
  for (let i = 0; i <= 10; i++) {
    const x = sidePadding + i * stepX;
    ctx.beginPath();
    ctx.moveTo(x, topPadding);
    ctx.lineTo(x, height - bottomPadding);
    ctx.stroke();
  }
};

// 绘制轴线和标签
const drawAxes = () => {
  const { width, height, axisColor, labelColor, topPadding, bottomPadding, sidePadding } = chartOptions;
  const maxX = Math.max(...props.data.map(point => point.x));
  const maxY = Math.max(...props.data.map(point => point.y));

  // 绘制 Y 轴
  const yAxisGradient = ctx.createLinearGradient(0, topPadding, 0, height - bottomPadding);
  yAxisGradient.addColorStop(0, axisColor[0]);
  yAxisGradient.addColorStop(1, axisColor[1]);
  ctx.strokeStyle = yAxisGradient;
  ctx.lineWidth = 1;
  ctx.beginPath();
  ctx.moveTo(sidePadding, topPadding);
  ctx.lineTo(sidePadding, height - bottomPadding);
  ctx.stroke();

  // 绘制 X 轴
  const xAxisGradient = ctx.createLinearGradient(0, height - bottomPadding, width, height - bottomPadding);
  xAxisGradient.addColorStop(0, axisColor[0]);
  xAxisGradient.addColorStop(1, axisColor[1]);
  ctx.strokeStyle = xAxisGradient;
  ctx.beginPath();
  ctx.moveTo(sidePadding, height - bottomPadding);
  ctx.lineTo(width - sidePadding, height - bottomPadding);
  ctx.stroke();

  // 绘制 Y 轴标签
  ctx.fillStyle = labelColor;
  ctx.font = '12px Arial';
  ctx.textAlign = 'right';
  for (let i = 0; i <= 10; i++) {
    const value = (maxY / 10) * i;
    const y = height - bottomPadding - (height - topPadding - bottomPadding) / 10 * i;
    ctx.fillText(value.toFixed(0), sidePadding - 10, y + 4);
  }

  // 绘制 X 轴标签
  ctx.textAlign = 'center';
  for (let i = 0; i <= 10; i++) {
    const value = (maxX / 10) * i;
    const x = sidePadding + (width - 2 * sidePadding) / 10 * i;
    ctx.fillText(value.toFixed(0), x, height - bottomPadding + 20);
  }
};

// 绘制散点
const drawScatter = () => {
  const { width, height, pointColor, topPadding, bottomPadding, sidePadding, pointRadius } = chartOptions;
  const maxX = Math.max(...props.data.map(point => point.x));
  const maxY = Math.max(...props.data.map(point => point.y));
  const scaleX = (width - 2 * sidePadding) / maxX; // X 轴缩放比例
  const scaleY = (height - topPadding - bottomPadding) / maxY; // Y 轴缩放比例

  ctx.fillStyle = pointColor;

  // 绘制数据点
  props.data.forEach(point => {
    const x = sidePadding + point.x * scaleX;
    const y = height - bottomPadding - point.y * scaleY;
    ctx.fillRect(x, y, pointRadius, pointRadius); // 使用 fillRect 绘制点
  });
};

// 渲染图表
const renderChart = () => {
  if (!chartCanvas.value) return;

  // 清空画布
  ctx.clearRect(0, 0, chartCanvas.value.width, chartCanvas.value.height);

  // 更新配置中的宽度和高度
  chartOptions.width = chartCanvas.value.width;
  chartOptions.height = chartCanvas.value.height;

  // 绘制背景、网格线、轴线和散点
  drawBackground();
  drawGridLines();
  drawAxes();
  drawScatter();
};

// 监听数据变化
watch(
    () => props.data,
    () => {
      renderChart();
    },
    { deep: true }
);

// 组件挂载时初始化
onMounted(() => {
  initCanvas();
  window.addEventListener('resize', initCanvas); // 监听窗口大小变化
});

// 组件卸载时移除监听器
onBeforeUnmount(() => {
  window.removeEventListener('resize', initCanvas);
});
</script>

<style scoped>
.chart-wrapper {
  width: 100%;
  height: 100%;
}
</style>